package com.yichi.detector;

import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.ColorMatrix;
import android.graphics.ColorMatrixColorFilter;
import android.graphics.Paint;
import android.graphics.PointF;
import android.graphics.Rect;

import com.google.mlkit.vision.face.Face;

import java.util.ArrayDeque;
import java.util.Queue;

public class StaticImageDetector {
    private static final float MOTION_THRESHOLD = 0.02f; // 运动差异阈值
    private Bitmap previousFrame;
    private final Rect faceRegion = new Rect();
    // 在StaticImageDetector类中添加
    private static final float TEXTURE_VARIANCE_THRESHOLD = 0.15f;
    private final Queue<PointF> movementQueue = new ArrayDeque<>(10);
    final float MOTION_WEIGHT = 0.4f;
    final float TEXTURE_WEIGHT = 0.3f;
    final float REFLECTION_WEIGHT = 0.3f;
    private float adaptiveThreshold = MOTION_THRESHOLD;
    // 添加缓存优化
    private Bitmap lastGrayCache;

    public boolean checkStatic(Bitmap currentFrame, Face face) {
        // 更新光照阈值
        updateThreshold(currentFrame);
        // 1. 获取人脸区域
        updateFaceRegion(face);

        // 初始化参考帧
        if (previousFrame == null) {
            previousFrame = cropFaceRegion(currentFrame);
            return false;
        }
        // 运动检测
        float motionScore = calculateMotion(currentFrame);
        boolean isStatic = motionScore < adaptiveThreshold;

        // 多维度检测
        boolean isTextureStatic = checkDynamicTexture(currentFrame);
        boolean hasReflection = checkScreenReflection(currentFrame);
        boolean isUnnatural = isUnnaturalMovement(face);

        // 综合评分
        float score = 0;
        score += isStatic ? MOTION_WEIGHT : 0;
        score += isTextureStatic ? TEXTURE_WEIGHT : 0;
        score += hasReflection ? REFLECTION_WEIGHT : 0;

        // 更新参考帧（智能更新）
        if (motionScore > adaptiveThreshold * 0.8f) {
            previousFrame = blendFrames(previousFrame, currentFrame);
        }

        return score > 0.6f || isUnnatural;
    }

    private Bitmap blendFrames(Bitmap prev, Bitmap current) {
        // 加权混合参考帧（减少突变影响）
        Bitmap blended = Bitmap.createBitmap(prev.getWidth(), prev.getHeight(),
                Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(blended);

        Paint paint = new Paint();
        paint.setAlpha(70);
        canvas.drawBitmap(prev, 0, 0, null);
        canvas.drawBitmap(current, 0, 0, paint);

        return blended;
    }

    private float calculateMotion(Bitmap current) {
        // 确保参考帧存在
        if (previousFrame == null) return 1.0f;

        // 优化缩放策略
        int minSize = Math.min(previousFrame.getWidth(), previousFrame.getHeight());
        int targetSize = Math.max(minSize / 4, 32); // 不低于32x32

        Bitmap prev = Bitmap.createScaledBitmap(previousFrame,
                targetSize, targetSize, true);
        Bitmap curr = Bitmap.createScaledBitmap(current,
                targetSize, targetSize, true);

        // 分块采样计算
        float totalDiff = 0;
        int blockSize = 4;
        int steps = targetSize / blockSize;

        for (int i=0; i<steps; i++) {
            for (int j=0; j<steps; j++) {
                int x = i * blockSize;
                int y = j * blockSize;
                totalDiff += calculateBlockDiff(prev, curr, x, y, blockSize);
            }
        }
        return totalDiff / (steps * steps);
    }

    private float calculateBlockDiff(Bitmap prev, Bitmap curr,
                                     int x, int y, int size) {
        float diff = 0;
        for (int dx=0; dx<size; dx++) {
            for (int dy=0; dy<size; dy++) {
                int px = x + dx;
                int py = y + dy;
                if (px >= prev.getWidth() || py >= prev.getHeight()) continue;

                diff += colorDiff(prev.getPixel(px, py), curr.getPixel(px, py));
            }
        }
        return diff / (size * size);
    }

    private void updateFaceRegion(Face face) {
        // 根据人脸框扩大20%区域
        faceRegion.set(
                (int) (face.getBoundingBox().centerX() - face.getBoundingBox().width() * 0.6),
                (int) (face.getBoundingBox().centerY() - face.getBoundingBox().height() * 0.6),
                (int) (face.getBoundingBox().centerX() + face.getBoundingBox().width() * 0.6),
                (int) (face.getBoundingBox().centerY() + face.getBoundingBox().height() * 0.6)
        );
    }

    private boolean isUnnaturalMovement(Face face) {
        // 分析头部运动轨迹
        PointF currentPos = new PointF(
                face.getBoundingBox().centerX(),
                face.getBoundingBox().centerY()
        );

        movementQueue.offer(currentPos);
        if (movementQueue.size() > 10) movementQueue.poll();

        // 计算运动方向变化频率
        int directionChanges = 0;
        PointF prev = null;
        PointF prevDir = null;
        for (PointF p : movementQueue) {
            if (prev != null) {
                PointF dir = new PointF(p.x - prev.x, p.y - prev.y);
                if (prevDir != null) {
                    float dot = dir.x * prevDir.x + dir.y * prevDir.y;
                    if (dot < 0) directionChanges++; // 方向突变
                }
                prevDir = dir;
            }
            prev = p;
        }

        // 高频方向变化可能是人为晃动
        return directionChanges > 5;
    }

    private boolean checkDynamicTexture(Bitmap frame) {
        // 使用缓存减少转换开销
        if (lastGrayCache == null ||
                lastGrayCache.getWidth() != frame.getWidth() ||
                lastGrayCache.getHeight() != frame.getHeight()) {
            lastGrayCache = toGrayscale(frame);
        }

        float variance = calculateLBPVariance(lastGrayCache);
        return variance < TEXTURE_VARIANCE_THRESHOLD;
    }

    private Bitmap toGrayscale(Bitmap src) {
        Bitmap gray = Bitmap.createBitmap(src.getWidth(), src.getHeight(), Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(gray);
        ColorMatrix matrix = new ColorMatrix();
        matrix.setSaturation(0);
        Paint paint = new Paint();
        paint.setColorFilter(new ColorMatrixColorFilter(matrix));
        canvas.drawBitmap(src, 0, 0, paint);
        return gray;
    }

    // 优化LBP计算
    private float calculateLBPVariance(Bitmap gray) {
        int step = 2; // 采样间隔
        int count = 0;
        float sum = 0, sumSq = 0;

        for (int y=1; y<gray.getHeight()-1; y+=step) {
            for (int x=1; x<gray.getWidth()-1; x+=step) {
                int center = gray.getPixel(x, y) & 0xFF;
                int code = 0;
                code |= (gray.getPixel(x - 1, y - 1) > center) ? 0x80 : 0;
                code |= (gray.getPixel(x, y - 1) > center) ? 0x40 : 0;
                code |= (gray.getPixel(x + 1, y - 1) > center) ? 0x20 : 0;
                code |= (gray.getPixel(x + 1, y) > center) ? 0x10 : 0;
                code |= (gray.getPixel(x + 1, y + 1) > center) ? 0x08 : 0;
                code |= (gray.getPixel(x, y + 1) > center) ? 0x04 : 0;
                code |= (gray.getPixel(x - 1, y + 1) > center) ? 0x02 : 0;
                code |= (gray.getPixel(x - 1, y) > center) ? 0x01 : 0;
                sum += code;
                sumSq += code * code;
                count++;
            }
        }
        return (sumSq - sum*sum/count) / count;
    }

    private Bitmap cropFaceRegion(Bitmap src) {
        try {
            return Bitmap.createBitmap(src,
                    Math.max(0, faceRegion.left),
                    Math.max(0, faceRegion.top),
                    Math.min(src.getWidth(), faceRegion.width()),
                    Math.min(src.getHeight(), faceRegion.height()));
        } catch (Exception e) {
            return src;
        }
    }

    private void updateThreshold(Bitmap frame) {
        // 根据图像亮度动态调整阈值
        float luminance = calculateLuminance(frame);
        adaptiveThreshold = MOTION_THRESHOLD * (luminance > 0.5f ? 0.8f : 1.2f);
    }

    private float calculateLuminance(Bitmap bitmap) {
        // 计算图像平均亮度
        float sum = 0;
        for (int x=0; x<bitmap.getWidth(); x+=5) {
            for (int y=0; y<bitmap.getHeight(); y+=5) {
                int color = bitmap.getPixel(x, y);
                sum += 0.299f*Color.red(color) + 0.587f*Color.green(color) + 0.114f*Color.blue(color);
            }
        }
        return sum / (bitmap.getWidth()*bitmap.getHeight()) / 255f;
    }

    private boolean checkScreenReflection(Bitmap frame) {
        int width = frame.getWidth();
        int height = frame.getHeight();
        int sampleCount = 0;
        int highlightCount = 0;

        // 检测高光区域
        for (int x = 0; x < width; x += 5) {
            for (int y = 0; y < height; y += 5) {
                int pixel = frame.getPixel(x, y);
                int r = Color.red(pixel);
                int g = Color.green(pixel);
                int b = Color.blue(pixel);

                if (r > 220 && g > 220 && b > 220 &&
                        Math.abs(r - g) < 30 && Math.abs(g - b) < 30) {
                    highlightCount++;
                }
                sampleCount++;
            }
        }

        // 高频亮度区域超过30%视为异常
        return (highlightCount / (float) sampleCount) > 0.3f;
    }

    // 优化后的颜色差异计算
    private float colorDiff(int c1, int c2) {
        float[] lab1 = rgbToLab(Color.red(c1), Color.green(c1), Color.blue(c1));
        float[] lab2 = rgbToLab(Color.red(c2), Color.green(c2), Color.blue(c2));
        return (float) Math.sqrt(
                Math.pow(lab1[0]-lab2[0], 2) * 0.7f +
                        Math.pow(lab1[1]-lab2[1], 2) * 0.2f +
                        Math.pow(lab1[2]-lab2[2], 2) * 0.1f
        ) / 100f;
    }

    private static float[] rgbToLab(int r, int g, int b) {
        // RGB转XYZ
        float[] xyz = new float[3];
        float rf = r / 255f;
        float gf = g / 255f;
        float bf = b / 255f;

        rf = (rf > 0.04045f) ? (float) Math.pow((rf + 0.055f) / 1.055f, 2.4f) : rf / 12.92f;
        gf = (gf > 0.04045f) ? (float) Math.pow((gf + 0.055f) / 1.055f, 2.4f) : gf / 12.92f;
        bf = (bf > 0.04045f) ? (float) Math.pow((bf + 0.055f) / 1.055f, 2.4f) : bf / 12.92f;

        xyz[0] = (rf * 0.4124f + gf * 0.3576f + bf * 0.1805f) * 100;
        xyz[1] = (rf * 0.2126f + gf * 0.7152f + bf * 0.0722f) * 100;
        xyz[2] = (rf * 0.0193f + gf * 0.1192f + bf * 0.9505f) * 100;

        // XYZ转Lab
        float[] ref = new float[]{95.047f, 100.0f, 108.883f};
        float x = xyz[0] / ref[0];
        float y = xyz[1] / ref[1];
        float z = xyz[2] / ref[2];

        x = (x > 0.008856f) ? (float) Math.pow(x, 1/3f) : (7.787f * x) + 16/116f;
        y = (y > 0.008856f) ? (float) Math.pow(y, 1/3f) : (7.787f * y) + 16/116f;
        z = (z > 0.008856f) ? (float) Math.pow(z, 1/3f) : (7.787f * z) + 16/116f;

        return new float[]{
                (116 * y) - 16,
                500 * (x - y),
                200 * (y - z)
        };
    }

    public void reset() {
        previousFrame = null;
    }
}
